package org.cybzacg.convert.converters.date;

import lombok.extern.slf4j.Slf4j;
import org.cybzacg.convert.annotation.Converter;
import org.cybzacg.convert.context.ConversionContext;
import org.cybzacg.convert.enums.ConversionPriority;
import org.cybzacg.convert.enums.ConversionType;
import org.cybzacg.convert.exception.ConversionException;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

/**
 * LocalDateTime转换器
 * 专门处理LocalDateTime类型的转换
 *
 * @author cybzacg.blog
 * @version 4.0
 * @since 3.0
 */
@Slf4j
@Converter(name = "LocalDateTimeConverter", priority = ConversionPriority.MEDIUM_HIGH, description = "LocalDateTime类型转换器，处理各种类型到java.time.LocalDateTime的转换", enabled = true, version = "4.0", author = "cybzacg.blog", supportedTypes = {
        LocalDateTime.class }, tags = { "localdatetime", "time", "conversion" })
public class LocalDateTimeConverter extends AbstractDateTimeConverter<LocalDateTime> {

    public LocalDateTimeConverter() {
        super(LocalDateTime.class, ConversionPriority.MEDIUM_HIGH);
    }

    @Override
    protected ConversionType getConversionType() {
        return ConversionType.LOCAL_DATE_TIME;
    }

    @Override
    protected LocalDateTime parseFromString(String str, DateTimeFormatter formatter) throws DateTimeParseException {
        // 先尝试解析为LocalDateTime
        try {
            return LocalDateTime.parse(str, formatter);
        } catch (DateTimeParseException e) {
            // 如果失败，尝试解析为LocalDate然后转换为LocalDateTime
            try {
                LocalDate date = LocalDate.parse(str, formatter);
                return date.atStartOfDay();
            } catch (DateTimeParseException ex) {
                throw e;
            }
        }
    }

    @Override
    protected LocalDateTime convertFromInstant(java.time.Instant instant, ConversionContext context) {
        return LocalDateTime.ofInstant(instant, DEFAULT_ZONE_ID);
    }

    @Override
    protected String[] getSupportedPatterns() {
        // 合并日期时间格式和日期格式
        String[] datetimePatterns = org.cybzacg.convert.constants.DateFormats.DATETIME_FORMAT_PATTERNS;
        String[] datePatterns = org.cybzacg.convert.constants.DateFormats.DATE_FORMAT_PATTERNS;
        String[] allPatterns = new String[datetimePatterns.length + datePatterns.length];
        System.arraycopy(datetimePatterns, 0, allPatterns, 0, datetimePatterns.length);
        System.arraycopy(datePatterns, 0, allPatterns, datetimePatterns.length, datePatterns.length);
        return allPatterns;
    }

    @Override
    protected LocalDateTime convertFromOtherDateTime(Object source, ConversionContext context) {
        // LocalDate转换
        if (source instanceof LocalDate localDate) {
            return localDate.atStartOfDay();
        }

        // LocalTime转换
        if (source instanceof LocalTime localTime) {
            return LocalDate.now().atTime(localTime);
        }

        // ZonedDateTime转换
        if (source instanceof ZonedDateTime zonedDateTime) {
            return zonedDateTime.toLocalDateTime();
        }

        // Year转换
        if (source instanceof Year year) {
            return year.atDay(1).atStartOfDay();
        }

        // YearMonth转换
        if (source instanceof YearMonth yearMonth) {
            return yearMonth.atDay(1).atStartOfDay();
        }

        return null;
    }

    @Override
    protected LocalDateTime getDefaultValue() {
        return org.cybzacg.convert.constants.DateTimeDefaults.LOCAL_DATETIME_DEFAULT;
    }
}
